package com.supermap.wzhy.module.data.service;

import com.supermap.wzhy.common.service.BaseService;
import com.supermap.wzhy.data.cons.CMicroMetaType;
import com.supermap.wzhy.data.cons.CMicroTableType;
import com.supermap.wzhy.entity.TMicroIdenmeta;
import com.supermap.wzhy.entity.TMicroTablemeta;
import com.supermap.wzhy.module.data.dao.MicroIdenmetaDao;
import com.supermap.wzhy.module.data.dao.MicroTablemetaDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by W.Qiong on 14-3-4.
 *
 * Modify by Linhao on 14-9-16
 */
@Service
public class MicroIdenmetaService extends BaseService {
    @Autowired
    private MicroIdenmetaDao microIdenmetaDao;
    @Autowired
    private MicroTablemetaDao microTablemetaDao;

    public TMicroIdenmeta create(int objecid, TMicroIdenmeta entity) {
        TMicroTablemeta tablemeta = microTablemetaDao.findOne(objecid);
        List<TMicroIdenmeta> idens = microIdenmetaDao.findObjectIdens(objecid) ;//已有指标
//        //相同指标复制就好
//        List<TMicroIdenmeta> codeList = microIdenmetaDao.checkNameIsExist(entity.getIdenName());
//        if (codeList.size() > 0) {
//            return null;
//        }
        if (tablemeta != null && entity != null) {
            String idenCode = generateCodeByName(entity.getIdenName(),idens);
            if (idenCode == null || idenCode.equals("")) {
                return null;
            }
            Integer maxOrder = getSurveyIndiMaxOrder(objecid);
            entity.setOrderby(maxOrder+1);
            entity.setTMicroTablemeta(tablemeta);
            entity.setIdenCode(idenCode);
            entity = microIdenmetaDao.save(entity);
            int metaType = tablemeta.getMicmetaType();
            if (metaType == CMicroMetaType.OBJECT_TYPE || metaType == CMicroMetaType.RANGE_TYPE) {
                addTableColumn(tablemeta.getTableName(), entity);
            }
            return entity ;
        }
        return null;
    }

    /**
     * 创建多个指标
     * @param objecid
     * @param newIdens
     * @return
     */
    public List<TMicroIdenmeta> create(int objecid, List<TMicroIdenmeta> newIdens) {
        TMicroTablemeta tablemeta = microTablemetaDao.findOne(objecid);
        List<TMicroIdenmeta> idens = microIdenmetaDao.findObjectIdens(objecid) ;//已有指标
        List<TMicroIdenmeta> creIdens = new ArrayList<>() ;//新建指标
        for(TMicroIdenmeta entity:newIdens){
            if (tablemeta != null && entity != null) {
                //可以自己制定指标代码
                if(null==entity.getIdenCode()||entity.getIdenCode().equals("")){
                    String idenCode = generateCodeByName(entity.getIdenName(),idens);
                    if (idenCode == null || idenCode.equals("")) {
                        return null;
                    }
                    entity.setIdenCode(idenCode);
                }
                Integer maxOrder = getSurveyIndiMaxOrder(objecid);
                entity.setOrderby(maxOrder+1);
                entity.setTMicroTablemeta(tablemeta);
                entity = microIdenmetaDao.save(entity);
                int metaType = tablemeta.getMicmetaType();
                //调查对象 统计范围  基层定报
                if (metaType == CMicroMetaType.OBJECT_TYPE || metaType == CMicroMetaType.RANGE_TYPE
                        ||metaType == CMicroMetaType.REGULARTABLE_TEM_TYPE) {
                    addTableColumn(tablemeta.getTableName(), entity);
                }
                creIdens.add(entity);
                idens.add(entity);
            }
        }
        return creIdens;
    }


    /**
     * 创建多个指标,sql语句一次性组装完成
     * @param objecid
     * @param newIdens
     * @return
     */
    public List<TMicroIdenmeta> createBatch(int objecid, List<TMicroIdenmeta> newIdens) {
        TMicroTablemeta tablemeta = microTablemetaDao.findOne(objecid);
        List<TMicroIdenmeta> idens = microIdenmetaDao.findObjectIdens(objecid) ;//已有指标
        List<TMicroIdenmeta> creIdens = new ArrayList<>() ;//新建指标
        String addColumnBatchSql = "alter table " + tablemeta.getTableName() + " add (";
        StringBuilder sqlBuilder = new StringBuilder();
        sqlBuilder.append(addColumnBatchSql);
        for(int i = 0; i < newIdens.size(); i++) {
            TMicroIdenmeta entity = newIdens.get(i);
            if(tablemeta != null && entity != null) {
                //可以自己制定指标代码
                if(null==entity.getIdenCode()||entity.getIdenCode().equals("")){
                    String idenCode = generateCodeByName(entity.getIdenName(),idens);
                    if (idenCode == null || idenCode.equals("")) {
                        return null;
                    }
                    entity.setIdenCode(idenCode);
                }
                Integer maxOrder = getSurveyIndiMaxOrder(objecid);
                entity.setOrderby(maxOrder+1);
                entity.setTMicroTablemeta(tablemeta);
                entity = microIdenmetaDao.save(entity);
                int metaType = tablemeta.getMicmetaType();
                //调查对象 统计范围  基层定报
                if (metaType == CMicroMetaType.OBJECT_TYPE || metaType == CMicroMetaType.RANGE_TYPE
                        ||metaType == CMicroMetaType.REGULARTABLE_TEM_TYPE) {
                    int idenType = entity.getIdenType();
                    int idenLen = entity.getIdenLength();
                    sqlBuilder.append(entity.getIdenCode());
                    if(idenType == 2) {
                        int preci = entity.getIdenPrecision();
                        sqlBuilder.append(" number(" + (preci>0?(idenLen>0?idenLen:10+","+preci):idenLen>0&&idenLen<=38?idenLen:10) + ") ");
                    } else if(idenType == 3) {
                        sqlBuilder.append(" Date ");
                    } else {
                        sqlBuilder.append(" varchar2(" + (idenLen > 0 ? idenLen : 300) + ") ");
                    }
                    sqlBuilder.append(",");
                }
                creIdens.add(entity);
                idens.add(entity);
            }
        }
        addColumnBatchSql = sqlBuilder.substring(0, sqlBuilder.length() - 1) + ")";
        microIdenmetaDao.executeBySql(addColumnBatchSql);
        return creIdens;
    }


    /**
     * 多条指标删除
     * @param objectid
     * @param ids
     * @return
     */
    public List<TMicroIdenmeta> delete(int objectid, int[] ids) {
        TMicroTablemeta tablemeta = microTablemetaDao.findOne(objectid);
        List<TMicroIdenmeta> re = new ArrayList<>();
        if(null == tablemeta){
            return  re ;
        }
        for(int i=0,size=ids.length; i<size; i++){
            int id = ids[i];
            TMicroIdenmeta idenmeta = microIdenmetaDao.findOne(id);
            if (null == idenmeta) {
                continue;
            }
            microIdenmetaDao.delete(idenmeta);
            re.add(idenmeta);
             //删除idenmeta,还要删除调查对象或者统计范围对应实体表字段
            int metaType = tablemeta.getMicmetaType();
            if (metaType == CMicroMetaType.OBJECT_TYPE || metaType == CMicroMetaType.RANGE_TYPE) {
                deleteTableColumn(tablemeta.getTableName(), idenmeta.getIdenCode());
            }
        }
        return re;
    }

    /**
     * 更新指标
     * @param id
     * @param entity
     * @return
     */
    public boolean update(int id, TMicroIdenmeta entity) {
        TMicroIdenmeta tMicroIdenmeta = microIdenmetaDao.getOne(entity.getMiimid());
        if (tMicroIdenmeta != null) {
            //把未更新的数据添加上去
            entity.setIdenCode(tMicroIdenmeta.getIdenCode());
            entity.setConfig(tMicroIdenmeta.getConfig());
            entity.setOrderby(tMicroIdenmeta.getOrderby());
            entity.setPermission(tMicroIdenmeta.getPermission());
            entity.setStatus(tMicroIdenmeta.getStatus());
            entity =  microIdenmetaDao.save(entity);
            TMicroTablemeta tablemeta = tMicroIdenmeta.getTMicroTablemeta() ;
            int metaType = tablemeta.getMicmetaType() ;
            //如果是调查对象实体表，要去修改对应的字段信息
            String tableName = tMicroIdenmeta.getTMicroTablemeta().getTableName() ;
            if(metaType == CMicroTableType.ACTUAL_TABLE_TYPE&&null != tableName){
                alterColumn(tableName,entity) ;
            }
            return true;
        }
        return false;
    }

    public List<TMicroIdenmeta> query(TMicroIdenmeta entity) {
        return microIdenmetaDao.findAll();
    }

    public TMicroIdenmeta one(int id) {
        return microIdenmetaDao.findOne(id);
    }

    public boolean importIdenmeta(int objectid, List<List<String>> datalist) {
        return false;
    }

    public List<TMicroIdenmeta> checkNameIsExist(String name){
        return  microIdenmetaDao.checkNameIsExist(name) ;
    }

    public List<TMicroIdenmeta> copyIdenmeta(int objectid, String idens) {
        List<TMicroIdenmeta> re = new ArrayList<>();
        TMicroTablemeta tablemeta = microTablemetaDao.findOne(objectid);
        if (tablemeta != null) {
            String[] idenArr = idens.split(",");
            int[] intArr = new int[idenArr.length];
            int num =0;
            for(String id :idenArr){
                if(null == id||"".equals(id)){
                    continue;
                }
               try {
                    int i = Integer.parseInt(id);
                   intArr[num++] = i ;
               }catch (Exception e){
                   e.printStackTrace();
               }
               continue;
            }
            List<TMicroIdenmeta> list = microIdenmetaDao.findByids(intArr);
            String[] fields=microIdenmetaDao.getTableFields(tablemeta.getTableName());
            Integer maxOrder = getSurveyIndiMaxOrder(objectid);
            for (TMicroIdenmeta templiden : list) {
                List<TMicroIdenmeta> checks = microIdenmetaDao.checkIsExist(objectid,templiden.getIdenCode());
                //已经存在 则跳过
                if(null!=checks&&checks.size()>0){
                    continue;
                }
                TMicroIdenmeta iden = new TMicroIdenmeta();
                String[] exclude = {"miimid"};
                iden = (TMicroIdenmeta) convertBeanTOBean(templiden, iden, exclude);
                iden.setOrderby(++maxOrder);
                iden.setTMicroTablemeta(tablemeta);
                iden = microIdenmetaDao.save(iden);
                if(null != iden){
                    re.add(iden);
                }
                //调查对象增加列
                boolean isFind=false;
                for(String field:fields){
                    if(field.equalsIgnoreCase(iden.getIdenCode())){
                        isFind=true;
                        break;
                    }
                }
                if(!isFind) {
                    addTableColumn(tablemeta.getTableName(), iden);
                }
            }
            return re;
        }
        return re;
    }

    private Integer getSurveyIndiMaxOrder(int objectid){
        Integer maxOrder = microIdenmetaDao.findMaxOrderBy(objectid);
        if(null == maxOrder){
            maxOrder =0 ;
        }
        return  maxOrder ;
    }

    //基层对象  全部可用字段
    public List<TMicroIdenmeta> findMicroIdentinfosByItem(int microid) {
        return microIdenmetaDao.findObjectIdens(microid);
    }

    public TMicroIdenmeta findOneIdenmeta(int microid, int indicatorid) {
        return microIdenmetaDao.findOneIdenmeta(microid, indicatorid);
    }

    public boolean exprotIdenmeta(int microid, String path) {
        return false;
    }

    //更新指标 修改实体表字段
    public  boolean alterColumn(String tableName,TMicroIdenmeta idenmeta){
        String idenCode = idenmeta.getIdenCode();
        int idenType = idenmeta.getIdenType() ;
        int  idenLen = idenmeta.getIdenLength() ;
        String sql = "alter table " + tableName + " modify  "+idenCode+" ";
        if(idenType == 2){
            int preci = idenmeta.getIdenPrecision() ;
            sql+= " number(" + (preci>0?(idenLen>0&&idenLen<=38?idenLen:38+","+preci):idenLen>0&&idenLen<=38?idenLen:38) + ") ";
        }else if(idenType ==3 ){
            sql +=" Date ";
        }else{
            sql+= " varchar(" + (idenLen>0?idenLen:300) + ") ";
        }
        sql +=" ";
        return  microIdenmetaDao.executeBySql(sql)>0 ;
    }

    //添加某个指标
    public boolean addTableColumn(String tableName, TMicroIdenmeta idenmeta) {
        String sql = "alter table " + tableName + " add ";
        if (tableName != null && idenmeta != null) {
            String idenCode = idenmeta.getIdenCode();
            String ideName = idenmeta.getIdenName() ;
            int idenType = idenmeta.getIdenType() ;
            int  idenLen = idenmeta.getIdenLength() ;
            sql += idenCode ;
            if(idenType == 2){
                int preci = idenmeta.getIdenPrecision() ;
                sql+= " number(" + (preci>0?(idenLen>0?idenLen:10+","+preci):idenLen>0&&idenLen<=38?idenLen:10) + ") ";
            }else if(idenType ==3 ){
                sql +=" Date ";
            }else{
                sql+= " varchar2(" + (idenLen>0?idenLen:300) + ") ";
            }
            int re = microIdenmetaDao.executeBySql(sql);

            sql =" comment on column "+tableName+"."+idenCode+" is '"+ideName +"'";
            re += microIdenmetaDao.executeBySql(sql) ;
            createColIndex(tableName,idenmeta);
            addColComments(tableName,idenmeta);
            return true;
        }
        return false;
    }

    public boolean deleteTableColumn(String tableName, String columnname) {
        String sql = "alter table " + tableName + " drop column " + columnname;
        try {
            int re = microIdenmetaDao.executeBySql(sql);
            return re > 0 ? true : false;
        } catch (Exception e) {
            return false;
        }
    }

    //给某列创建索引
    private boolean createColIndex(String tableName, TMicroIdenmeta iden) {
            String strSql = "";
            String ideCode = iden.getIdenCode() ;
//            String index = "IND_" + tableName + "_" + ideCode; //INDEX->IND 避免索引名过长报错
            String index = "IND_" + tableName.replace("MICROTABLE","TABLE") + "_" + ideCode; //INDEX->IND 避免索引名过长报错
            strSql = "create index " + index + " on " + tableName + " (" + ideCode + ")";
            return  microTablemetaDao.executeBySql(strSql)>0;
    }

    //创建单列备注
    private boolean addColComments( String tableName, TMicroIdenmeta iden){
        String ideCode = iden.getIdenCode() ;
        String ideName = iden.getIdenName() ;
        String sql = "comment on column "+tableName+"."+ideCode+" is '"+ideName +"'";
        return  microTablemetaDao.executeBySql(sql)>0;
    };

    /**
     * 创建指标编码
     * @param name
     * @param existIdens 已存在指标，避免同一数据下编码重复而报错
     * @return
     */
    public String generateCodeByName(String name,List<TMicroIdenmeta> existIdens) {
        List<TMicroIdenmeta> codeList = microIdenmetaDao.checkNameIsExist(name);
        String code = "";
        boolean isSame = true ; //是否相同指标名称下的指标编码为同一个  常用固定指标应该为同一个！！！
        for(TMicroIdenmeta i :codeList){
            if(code.equals("")){
                code =  i.getIdenCode() ;
            }
            if(!code.equals(i.getIdenCode())){
                isSame = false ;
                break;
            }
        }
        //检查已有指标是否存在相同了，如果存在另外编码
        if(isSame&&!code.equals("")){
            boolean isExist = false ;
            for(TMicroIdenmeta i:existIdens){
                if(i.getIdenCode().equals(code)){
                    isExist = true ;
                }
            }
            if(!isExist){
                return  code ;
            }
        }
        //B开头的 可能有些字段是自己加进来像BX01,不能直接截取
        String maxCode = microIdenmetaDao.findMaxCode();
        if(maxCode==null){
            return "B00001" ;
        }
        int number =0;
        try {
            number = Integer.parseInt(maxCode.substring(1));
        }catch (Exception e){
            System.out.println("获取指标代码数值最大值异常:"+maxCode);
            number =0;
        }
        return "B" + String.format("%05d", number + 1);
    }



    /**
     * 根据调查对象 和 指标code 获取枚举内码
     * @param mitmid
     * @param idencode
     * @return
     */
    public int getMiitidByIdenCode(int mitmid ,String idencode){
        TMicroIdenmeta microIdenmeta = microIdenmetaDao.findByIdenCode(mitmid,idencode);
        int miitid = microIdenmeta.getTMicroIdent().getMiitid();
        return miitid;
    }
}
